`include "chunjun_define.sv" 
`include "chunjun_lib_define.sv" 

//================================================================================================
// File Name   : wing_cbb_prefix_counter.sv
// Description : Find the Nth 1 in the bitmap
//================================================================================================
module wing_cbb_prefix_counter
#(
    parameter DATA_WIDTH = 8,
    parameter NUM_OF_ONES = 3
)
(
   input   logic [DATA_WIDTH-1:0] data, //input bitmap
   output  logic [NUM_OF_ONES:0] cnt_oh //output result vector
);

    logic [NUM_OF_ONES:0][DATA_WIDTH-1:0][DATA_WIDTH-1:0] x;
 
if(DATA_WIDTH == 5 && NUM_OF_ONES == 1) begin : prefix_counter_gen_5_1
    assign x[0][4][4] = ~data[4];
    assign x[0][3][3] = ~data[3];
    assign x[0][2][2] = ~data[2];
    assign x[0][3][2] = (x[0][3][3] & x[0][2][2]);
    assign x[0][1][1] = ~data[1];
    assign x[0][0][0] = ~data[0];
    assign x[0][1][0] = (x[0][1][1] & x[0][0][0]);
    assign x[0][3][0] = (x[0][3][2] & x[0][1][0]);
    assign x[0][4][0] = (x[0][4][4] & x[0][3][0]);
    assign cnt_oh[0] = x[0][4][0];
    assign x[1][0][0] = data[0];
    assign x[1][1][1] = data[1];
    assign x[1][1][0] = (x[0][1][1] & x[1][0][0]) | (x[1][1][1] & x[0][0][0]);
    assign x[1][2][2] = data[2];
    assign x[1][3][3] = data[3];
    assign x[1][3][2] = (x[0][3][3] & x[1][2][2]) | (x[1][3][3] & x[0][2][2]);
    assign x[1][3][0] = (x[0][3][2] & x[1][1][0]) | (x[1][3][2] & x[0][1][0]);
    assign x[1][4][4] = data[4];
    assign x[1][4][0] = (x[0][4][4] & x[1][3][0]) | (x[1][4][4] & x[0][3][0]);
    assign cnt_oh[1] = x[1][4][0];
end
if(DATA_WIDTH == 5 && NUM_OF_ONES == 0) begin : prefix_counter_gen_5_0
    assign x[0][4][4] = ~data[4];
    assign x[0][3][3] = ~data[3];
    assign x[0][2][2] = ~data[2];
    assign x[0][3][2] = (x[0][3][3] & x[0][2][2]);
    assign x[0][1][1] = ~data[1];
    assign x[0][0][0] = ~data[0];
    assign x[0][1][0] = (x[0][1][1] & x[0][0][0]);
    assign x[0][3][0] = (x[0][3][2] & x[0][1][0]);
    assign x[0][4][0] = (x[0][4][4] & x[0][3][0]);
    assign cnt_oh[0] = x[0][4][0];
end
if(DATA_WIDTH == 3 && NUM_OF_ONES == 0) begin : prefix_counter_gen_3_0
    assign x[0][2][2] = ~data[2];
    assign x[0][1][1] = ~data[1];
    assign x[0][0][0] = ~data[0];
    assign x[0][1][0] = (x[0][1][1] & x[0][0][0]);
    assign x[0][2][0] = (x[0][2][2] & x[0][1][0]);
    assign cnt_oh[0] = x[0][2][0];
end
if(DATA_WIDTH == 1 && NUM_OF_ONES == 0) begin : prefix_counter_gen_1_0
    assign x[0][0][0] = ~data[0];
    assign cnt_oh[0] = x[0][0][0];
end
if(DATA_WIDTH == 7 && NUM_OF_ONES == 1) begin : prefix_counter_gen_7_1
    assign x[0][6][6] = ~data[6];
    assign x[0][5][5] = ~data[5];
    assign x[0][4][4] = ~data[4];
    assign x[0][5][4] = (x[0][5][5] & x[0][4][4]);
    assign x[0][6][4] = (x[0][6][6] & x[0][5][4]);
    assign x[0][3][3] = ~data[3];
    assign x[0][2][2] = ~data[2];
    assign x[0][3][2] = (x[0][3][3] & x[0][2][2]);
    assign x[0][1][1] = ~data[1];
    assign x[0][0][0] = ~data[0];
    assign x[0][1][0] = (x[0][1][1] & x[0][0][0]);
    assign x[0][3][0] = (x[0][3][2] & x[0][1][0]);
    assign x[0][6][0] = (x[0][6][4] & x[0][3][0]);
    assign cnt_oh[0] = x[0][6][0];
    assign x[1][0][0] = data[0];
    assign x[1][1][1] = data[1];
    assign x[1][1][0] = (x[0][1][1] & x[1][0][0]) | (x[1][1][1] & x[0][0][0]);
    assign x[1][2][2] = data[2];
    assign x[1][3][3] = data[3];
    assign x[1][3][2] = (x[0][3][3] & x[1][2][2]) | (x[1][3][3] & x[0][2][2]);
    assign x[1][3][0] = (x[0][3][2] & x[1][1][0]) | (x[1][3][2] & x[0][1][0]);
    assign x[1][4][4] = data[4];
    assign x[1][5][5] = data[5];
    assign x[1][5][4] = (x[0][5][5] & x[1][4][4]) | (x[1][5][5] & x[0][4][4]);
    assign x[1][6][6] = data[6];
    assign x[1][6][4] = (x[0][6][6] & x[1][5][4]) | (x[1][6][6] & x[0][5][4]);
    assign x[1][6][0] = (x[0][6][4] & x[1][3][0]) | (x[1][6][4] & x[0][3][0]);
    assign cnt_oh[1] = x[1][6][0];
end
if(DATA_WIDTH == 7 && NUM_OF_ONES == 0) begin : prefix_counter_gen_7_0
    assign x[0][6][6] = ~data[6];
    assign x[0][5][5] = ~data[5];
    assign x[0][4][4] = ~data[4];
    assign x[0][5][4] = (x[0][5][5] & x[0][4][4]);
    assign x[0][6][4] = (x[0][6][6] & x[0][5][4]);
    assign x[0][3][3] = ~data[3];
    assign x[0][2][2] = ~data[2];
    assign x[0][3][2] = (x[0][3][3] & x[0][2][2]);
    assign x[0][1][1] = ~data[1];
    assign x[0][0][0] = ~data[0];
    assign x[0][1][0] = (x[0][1][1] & x[0][0][0]);
    assign x[0][3][0] = (x[0][3][2] & x[0][1][0]);
    assign x[0][6][0] = (x[0][6][4] & x[0][3][0]);
    assign cnt_oh[0] = x[0][6][0];
end
endmodule

`include "chunjun_undefine.sv" 
